package com.weibo.basic.alg.alert.server.service;

import com.google.common.base.Joiner;
import com.google.common.collect.Sets;
import com.weibo.basic.alg.alert.common.entity.SendMessageRequest;
import com.weibo.basic.alg.alert.server.config.AlarmConfig;
import com.weibo.basic.alg.alert.server.config.WechatConfig;
import com.weibo.basic.alg.alert.server.domain.PostMsgReturn;
import com.weibo.basic.alg.alert.server.domain.RetryTooManyTimes;
import com.weibo.basic.alg.alert.server.domain.WechatTextMessage;
import com.weibo.basic.alg.alert.server.domain.WechatTextMessage.Text;
import com.weibo.basic.alg.alert.server.entity.Alert;
import com.weibo.basic.alg.alert.server.util.DateUtils;
import java.io.IOException;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import retrofit2.Response;

@Service
@Slf4j
public class WechatAlertImpl implements IAlertService {

    @Autowired
    private WechatAPI wechatAPI;

    @Autowired
    private WechatConfig wechatConfig;

    @Autowired
    private TokenService tokenService;

    @Autowired
    private AlarmConfig alarmConfig;


    @Override
    public boolean alert(Alert alert) throws RetryTooManyTimes {
        String msg = alert.resolveAlertMsg();
        WechatTextMessage textMessage = new WechatTextMessage();
        textMessage.setTouser(Joiner.on("|").join(alarmConfig.getAlarmUsers()));
        textMessage.setAgentid(wechatConfig.getAgentId());
        textMessage.setText(new Text(insertAlarmTime(msg)));
        log.info("wechat message is {}", textMessage);
        return doAlert(textMessage, false, 0);
    }

    private String insertAlarmTime(String msg) {

        return "报警时间: " + DateUtils.now() + "\n" + msg;
    }

    @Override
    public boolean alert(SendMessageRequest sendMessageRequest) throws RetryTooManyTimes {
        String msg = sendMessageRequest.getMessage();
        WechatTextMessage textMessage = new WechatTextMessage();
        if (null != sendMessageRequest.getReceivers() && !sendMessageRequest.getReceivers().isEmpty()) {
            textMessage
                .setTouser(Joiner.on("|").join(
                    Sets.newHashSet(sendMessageRequest.getReceivers()).stream().map(e -> e.trim()).collect(
                        Collectors.toList())));
        } else {
            textMessage.setTouser(Joiner.on("|").join(alarmConfig.getAlarmUsers()));
        }
        textMessage.setAgentid(wechatConfig.getAgentId());
        textMessage.setText(new Text(insertAlarmTime(msg)));
        log.info("wechat message is {}", textMessage);
        return doAlert(textMessage, false, 0);
    }

    private boolean doAlert(WechatTextMessage textMessage, boolean refreshToken, int retryCount)
        throws RetryTooManyTimes {
        if (retryCount > 3) {
            log.warn("retry too many times,return immediately");
            throw new RetryTooManyTimes();
        }
        String token = "";
        try {
            token = tokenService.getToken(refreshToken);
        } catch (IOException e) {
            log.error("getToken failed", e);
            return doAlert(textMessage, true, retryCount + 1);
        }

        Response<PostMsgReturn> ret = null;
        try {
            ret = wechatAPI.postMessage(token, textMessage)
                .execute();
            if (ret.isSuccessful()) {
                PostMsgReturn postMsgReturn = ret.body();
                if (postMsgReturn.isSuccess()) {
                    return true;
                } else {
                    log.error("send {} to wechat faield,error is {}", textMessage, postMsgReturn);
                    //token is invalid or token is expired
                    if (postMsgReturn.getErrcode().equals(40014) || postMsgReturn.getErrcode().equals(42001)) {
                        return doAlert(textMessage, true, retryCount + 1);
                    }
                }
            } else {
                log.error("send {} to wechat faield,error is {}", textMessage, ret.message());
            }
        } catch (IOException e) {
            log.error("post message failed", e);
        }
        return doAlert(textMessage, false, retryCount + 1);
    }
}
